//
//  Request.swift
//  ExRequest
//
//  Created by 王渊鸥 on 2018/8/10.
//  Copyright © 2018 WangYuanOu. All rights reserved.
//

import Foundation
import ExType

private var g_request_semaphore = DispatchSemaphore(value: 0)

public enum HTTPResponse {
    case json([String:Any])
    case text(String)
    case image(UIImage?)
    case data(Data)
    case error(Error?)
    
    public static func parse(data:Data?, result:URLResponse?, error:Error?) -> HTTPResponse {
        guard let data = data else {
            return HTTPResponse.error(error)
        }
        
        if let type = result?.mimeType {
            if type.hasPrefix("image") {
                let image = UIImage(data: data)
                return HTTPResponse.image(image)
            } else if type.hasPrefix("text") {
                if let text = String(data: data, encoding: String.Encoding.utf8) {
                    if let json = ex_json(text: text) {
                        return HTTPResponse.json(json)
                    } else {
                        return HTTPResponse.text(text)
                    }
                }
            }
        }
        
        return HTTPResponse.data(data)
    }
}

private func simple_request(request:URLRequest) -> HTTPResponse? {
    let session = URLSession()
    var result:HTTPResponse?
    
    session.dataTask(with: request) { (data, response, error) in
        result = HTTPResponse.parse(data: data, result: response, error: error)
        
        g_request_semaphore.signal()
    }
    
    g_request_semaphore.wait()
    
    return result
}

public func ex_request(url:URL) -> HTTPResponse? {
    let request = URLRequest(url: url)
    return simple_request(request: request)
}

public func ex_request(url:URL, postBoundry:[String:Any]) -> HTTPResponse? {
    let request = NSMutableURLRequest(url: url)
    request.httpMethod = "POST"
    let parameters:[String:BoundryValue] = postBoundry.map({ (k, v) -> (String, BoundryValue)? in
        return (k, BoundryValue.text(v as! String))
    })
    request.httpBody = ex_boundry(boundry: "__ExRequest__", values: parameters)
    
    return simple_request(request: request as URLRequest)
}

public func ex_request(url:URL, putBoundry:[String:BoundryValue]) -> HTTPResponse? {
    let request = NSMutableURLRequest(url: url)
    request.httpMethod = "PUT"
    request.httpBody = ex_boundry(boundry: "__ExRequest__", values: putBoundry)
    
    return simple_request(request: request as URLRequest)
}

public func ex_request(url:URL, postQuery:[String:Any]) -> HTTPResponse? {
    let request = NSMutableURLRequest(url: url)
    request.httpBody = ex_parameters(params: postQuery).data(using: String.Encoding.utf8)
    
    return simple_request(request: request as URLRequest)
}

private func simple_request(request:URLRequest, response:@escaping (HTTPResponse)->()) {
    let session = URLSession()
    session.dataTask(with: request) { (data, result, error) in
        let resp = HTTPResponse.parse(data: data, result: result, error: error)
        response(resp)
    }
}

public func ex_request(url:URL, response:@escaping (HTTPResponse)->()) {
    let request = URLRequest(url: url)
    simple_request(request: request, response: response)
}

public func ex_request(url:URL, postBoundry:[String:Any], response:@escaping (HTTPResponse)->()) {
    let request = NSMutableURLRequest(url: url)
    request.httpMethod = "POST"
    let parameters:[String:BoundryValue] = postBoundry.map({ (k, v) -> (String, BoundryValue)? in
        return (k, BoundryValue.text(v as! String))
    })
    request.httpBody = ex_boundry(boundry: "__ExRequest__", values: parameters)
    
    simple_request(request: request as URLRequest, response: response)
}

public func ex_request(url:URL, putBoundry:[String:BoundryValue], response:@escaping (HTTPResponse)->()) {
    let request = NSMutableURLRequest(url: url)
    request.httpMethod = "PUT"
    request.httpBody = ex_boundry(boundry: "__ExRequest__", values: putBoundry)
    
    simple_request(request: request as URLRequest, response: response)
}

public func ex_request(url:URL, postQuery:[String:Any], response:@escaping (HTTPResponse)->()) {
    let request = NSMutableURLRequest(url: url)
    request.httpBody = ex_parameters(params: postQuery).data(using: String.Encoding.utf8)
    
    simple_request(request: request as URLRequest, response: response)
}

